#include <stdio.h>
#include "ecc.h"
#include "sha384.h"

void PrintHexBuf(char *title, uint8_t *data, uint16_t len)
{
    printf("%s:", title);
    for (size_t i = 0; i < len; i++) {
        if (i % 16 == 0)
            printf("\n");
        printf("0x%02X, ", data[i]);
    }
    printf("\n");
}

void ReadOpensslPriKey(uint8_t prikey[ECC_BYTES], char *prikey_str)
{
    for (int i = 0; i < ECC_BYTES; i++) {
        sscanf(prikey_str, "%2x:", &prikey[i]);
        prikey_str += 3;
    }
}

void ReadOpensslPubKey(uint8_t pubkey[ECC_BYTES + 1], char *pubkey_str)
{
    uint8_t last_data;
    pubkey_str += 3;

    for (size_t i = 0; i < ECC_BYTES; i++) {
        sscanf(pubkey_str, "%2x:", &pubkey[i + 1]);
        pubkey_str += 3;
    }
    for (size_t i = 0; i < ECC_BYTES; i++) {
        sscanf(pubkey_str, "%2x:", &last_data);
        pubkey_str += 3;
    }
    if (last_data % 2 == 1)
        pubkey[0] = 0x03;
    else
        pubkey[0] = 0x02;
}

char openssl_prikey[] = "00:a2:97:b4:b5:1b:48:ce:26:59:7e:ca:70:bf:b2:97:02:23:a6:64:b5:fc:98:ca:44:a0:06:0d:35:93:7a:6b:05:88:e6:c3:2f:a2:e7:12:4a:02:f5:43:7c:a2:fb:35";
char openssl_pubkey[] = "04:f0:47:f8:34:81:b4:84:68:1a:33:c9:5f:ea:9f:48:c0:15:11:7c:b5:a0:40:46:0f:f5:c6:1c:02:f2:34:91:f8:aa:4a:97:d3:19:6e:50:3a:78:0f:ff:c8:1f:a6:74:ec:89:78:c4:f7:57:9a:73:ca:df:20:b3:54:ad:11:aa:d6:0d:1e:dd:5c:bf:bd:a1:3e:6d:3f:82:28:41:cd:75:c6:ab:4f:1e:8f:45:e4:dd:1a:d3:10:35:9b:56:37:5b:3b";
char test[] = "hello";
uint8_t prikey[ECC_BYTES], pubkey[ECC_BYTES + 1], hash[ECC_BYTES], hash_reverse[ECC_BYTES], signature[ECC_BYTES * 2];
uint8_t ssl_sig[ECC_BYTES * 2] = {
    0xaa, 0xc6, 0x8c, 0x0d, 0x2f, 0x18, 0x87,
    0xbc, 0x96, 0x1c, 0xa4, 0x40, 0x01, 0xec, 0x7a, 0x71, 0xbd, 0x13, 0x3c,
    0xd4, 0x74, 0xfc, 0xce, 0x22, 0xbf, 0x64, 0x57, 0x8a, 0x86, 0xde, 0x1e,
    0xc4, 0x50, 0x75, 0x7b, 0x47, 0xc2, 0x0f, 0x2f, 0x31, 0x47, 0xa2, 0xa9,
    0x0b, 0xba, 0xe0, 0x40, 0xdb, 0xd9, 0x5a, 0xff, 0xf3,
    0xe0, 0x08, 0xf8, 0x2c, 0x1b, 0x45, 0x0c, 0x2d, 0xcf, 0x4a, 0x57, 0xa7,
    0x97, 0x49, 0x32, 0x17, 0x27, 0x63, 0x19, 0x8c, 0x9c, 0x2f, 0x04, 0x88,
    0x61, 0x52, 0x55, 0x55, 0x8c, 0xc2, 0xda, 0x92, 0xca, 0x56, 0xc0, 0x1b,
    0xfd, 0x43, 0x1e, 0xf9, 0x59, 0x24, 0x13, 0x20};
uint8_t ssl_sig_reverse[ECC_BYTES * 2];
void main(void)
{
    printf("Test Starting...\n");

    printf("\nCalculate the hash of \"hello\" string\n");
    sha384(test, 5, hash);
    PrintHexBuf("Hash", hash, ECC_BYTES);

    printf("\nGenerate keys\n");
    ecc_make_key(pubkey, prikey);
    printf("\nCalculate ECDSA sign\n");
    ecdsa_sign(prikey, hash, signature);
    printf("\nVerify the sign\n");
    if (ecdsa_verify(pubkey, hash, signature))
        printf("Verify OK\n");
    else
        printf("Verify FAIL\n");

    printf("\nRead prikey and pubkey from openssl generation format\n");
    ReadOpensslPriKey(prikey, openssl_prikey);
    ReadOpensslPubKey(pubkey, openssl_pubkey);
    PrintHexBuf("PrivKey", prikey, ECC_BYTES);
    PrintHexBuf("PubKey", pubkey, ECC_BYTES + 1);

    printf("\nCalculate ECDSA sign\n");
    ecdsa_sign(prikey, hash, signature);
    PrintHexBuf("Signature", signature, ECC_BYTES * 2);

    printf("\nVerify the sign\n");
    if (ecdsa_verify(pubkey, hash, signature))
        printf("Verify OK\n");
    else
        printf("Verify FAIL\n");
    PrintHexBuf("Hash", hash, ECC_BYTES);

    printf("\nVerify the sign from openssl\n");

    for (int i = 0; i < ECC_BYTES; i++) {
        hash_reverse[i] = hash[ECC_BYTES - 1 - i];
        ssl_sig_reverse[i] = ssl_sig[ECC_BYTES - 1 - i];
        ssl_sig_reverse[i + ECC_BYTES] = ssl_sig[2 * ECC_BYTES - 1 - i];
    }
    if (ecdsa_verify(pubkey, hash, ssl_sig))
        printf("Verify OK\n");
    else
        printf("Verify FAIL\n");
    
    return 0;
}